<template>
  <div class="table-select" :style="{width: common.isNumber(inputWidth)?inputWidth+'px':inputWidth}">
    <el-popover ref="table-select" v-model="showPopover" :disabled="disabled" :width="popoverWidth" :trigger="trigger" placement="bottom-start" popper-class="input-popover" @show="onShow" @hide="()=>{treeSuffixIcon='el-icon-yrt-xiangxiajiantou1'}">
      <el-input slot="reference" ref="input" v-model="currentValue" :style="{width: common.isNumber(inputWidth)?inputWidth+'px':inputWidth}" :placeholder="placeholder" :disabled="disabled" :suffix-icon="treeSuffixIcon" :size="size" class="input no-bg" @focus="(event)=>{onFocus($refs['input'], currentRow, event);}" @change="(val)=>{onInputChange($refs['input'], val);}" @keyup.native="(event)=>{onInputKeyup($refs['input'], event);}" @keydown.native="(event)=>{onInputKeydown($refs['input'], event);}">
      </el-input>
      <el-table ref="dropdownTable" :data="dataList" :max-height="tableMaxHeight" size="mini" highlight-current-row style="width: 100%" class="dropdown-table" @current-change="onCurrentChange" @row-click="onRowClick">
        <el-table-column type="index" width="40" label="#">
          <template slot-scope="{row, column, $index}">
            <div :ref="'row'+$index">{{ $index }}</div>
          </template>
        </el-table-column>
        <slot name="column">
          <el-table-column v-for="(col, index) in columns" :key="index" :property="col.prop" :label="col.label" :width="col.width">
          </el-table-column>
        </slot>
      </el-table>
    </el-popover>
  </div>
</template>

<script>
export default {
  name: "table-select",
  props: {
    // 表单数据
    formData: {
      type: Object,
      default: () => {
        return {};
      }
    },
    // 字段信息
    field: {
      type: Object,
      default: () => {
        return {};
      }
    },
    // 下拉框绑定值
    value: {
      type: String,
      default: null
    },
    // 字段中文名
    label: {
      type: String,
      default: null
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 弹窗宽度
    popoverWidth: {
      type: [Number, String],
      default: "400px"
    },
    // 表格高度
    tableMaxHeight: {
      type: Number,
      default: 300
    },
    // 输入框宽度
    inputWidth: {
      type: [Number, String],
      default: "100%"
    },
    // 提示内容
    placeholder: {
      type: String,
      default: null
    },
    // 配置选项
    props: {
      type: Object,
      default: () => {
        return {
          label: "label",
          value: "value"
        };
      }
    },
    // 表格数据
    tableData: {
      type: Array,
      default: () => {
        return [];
      }
    },
    // 值字段名
    valueField: {
      type: String,
      default: "value"
    },
    // 名称字段名
    labelField: {
      type: String,
      default: "label"
    },
    // 输入框尺寸大小
    size: {
      type: String,
      default: "medium"
    },
    // 弹出框触发事件方式
    trigger: {
      type: String,
      default: "click"
    },
    // 字段列表
    columns: {
      type: Array,
      default: () => {
        return [];
      }
    }
  },
  data () {
    return {
      // TREE选择器右侧下拉框
      treeSuffixIcon: "el-icon-yrt-xiangxiajiantou1",
      // 是否显示下拉框
      isShowPopover: false,
      currentRow: null,
      // 键盘按下时延时handle
      searchHandle: null,
      // 当前数据
      dataList: []
    };
  },
  computed: {
    // 当前值
    currentValue: {
      get: function () {
        return this.value;
      },
      set: function (val) {
        this.$emit("input", val);
      }
    },
    // 当前值
    showPopover: {
      get: function () {
        return this.isShowPopover;
      },
      set: function (val) {
        this.isShowPopover = val;
      }
    }
  },
  // 监听数据
  watch: {
    tableData: {
      handler: function (newVal, oldVal) {
        this.dataList = newVal;
      },
      deep: true,
      immediate: true
    },
    value: {
      handler: function (newVal, oldVal) {
        if (!newVal) {
          this.currentRow = null;
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted () {
    // 初始化下拉框数据
    this.loadData(this.$refs.input, true);
  },
  methods: {
    // input change事件
    onInputChange (ref, val) {
      this.$emit("on-change", ref, val);
    },
    // input keyup事件
    onInputKeyup (ref, event) {
      // Up key
      if (event.keyCode === 38) {
        let existIndex = this.dataList.findIndex(item => {
          return item[this.labelField] === this.currentValue;
        });
        existIndex -= 1;
        if (existIndex < 0) {
          existIndex = this.dataList.length - 1;
        }
        const itemData = this.dataList.find((item, index) => {
          return index === existIndex;
        });
        this.currentValue = itemData[this.labelField];
        this.$refs.dropdownTable.setCurrentRow(itemData);
        this.onRowChange(ref, itemData); // 自动设置值
        this.$emit("on-row-change", ref, itemData, event);
        return false;
      }
      // Down key
      if (event.keyCode === 40) {
        let existIndex = this.dataList.findIndex(item => {
          return item[this.labelField] === this.currentValue;
        });
        existIndex += 1;
        if (existIndex >= this.dataList.length) {
          existIndex = 0;
        }
        const itemData = this.dataList.find((item, index) => {
          return index === existIndex;
        });
        this.currentValue = itemData[this.labelField];
        this.$refs.dropdownTable.setCurrentRow(itemData);
        this.$emit("on-row-change", ref, itemData, event);
        return false;
      }
      // Enter key
      if (event.keyCode === 13) {
        this.showPopover = !this.showPopover;
        this.$refs.input.select();
        this.$refs.input.focus();
        return;
      }
      // 取消请求加载数据
      if (this.searchHandle) {
        clearTimeout(this.searchHandle);
        this.searchHandle = null;
      }
      this.searchHandle = setTimeout(() => {
        this.loadData(ref, false);
        clearTimeout(this.searchHandle);
        this.searchHandle = null;
      }, 800);
      this.$emit("on-key-up", ref, this.currentValue, event, this.dataList);
    },
    // input keydown事件
    onInputKeydown (ref, event) {
      this.$emit("on-key-down", ref, this.currentValue, event, this.dataList);
    },
    // 当值当前行
    setCurrentIndex (existIndex) {
      const itemData = this.dataList.find((item, index) => {
        return index === existIndex;
      });
      if (itemData) {
        this.currentValue = itemData[this.labelField];
        this.$refs.dropdownTable.setCurrentRow(itemData);
      }
      // this.$refs["table-select"].doClose();
    },
    // 判断是否有选中项
    getCurrrentIndex () {
      const existIndex = this.dataList.findIndex(item => {
        return item[this.labelField] === this.currentValue;
      });
      return existIndex;
    },
    // 关闭下拉框
    doClose () {
      this.$refs["table-select"].doClose();
    },
    // 获得焦点
    onFocus (ref, val, event) {
      var disabled = ref.$attrs.disabled;
      if (disabled) return;

      this.$emit("on-focus", ref, val, event);
    },
    // 当前行改变
    onCurrentChange (val) {
      if (!val) {
        return;
      }
      this.currentRow = val;
      this.currentValue = this.currentRow[this.labelField];
      this.$emit("on-row-change", this.$refs.input, this.currentRow);
    },
    // 单击当前行
    onRowClick (row, column, event) {
      this.currentRow = row;
      this.onRowChange(this.$refs.input, row); // 自动设置值
      this.$emit("on-row-click", this.$refs.input, this.currentRow);
      this.showPopover = false;
      this.$refs["table-select"].doClose();
    },
    // 设置焦点
    focus () {
      this.$refs.input.focus();
    },
    // 设置选中
    select () {
      this.$refs.input.select();
    },
    // 下拉框输入改变后加载数据
    loadData (ref, isInit) {
      if (!this.field || !this.field.options) return;

      const val = !isInit ? this.currentValue : "";
      const url = this.field.options.url;
      if (url) {
        // if (!val && !isInit) {
        //   return;
        // }
        if (!this.field.options.searchFields) {
          this.$message.error(`字段【${this.field.options.prop}】未设置查询字段！`);
          return;
        }
        const params = {
          name: val,
          searchFields: this.field.options.searchFields.split(",")
        };
        this.common.ajax(
          url,
          params,
          res => {
            this.common.showMsg(res);
            this.dataList = [];
            if (res.result) {
              res.data.forEach(item => {
                this.$set(this.dataList, this.dataList.length, item);
              });
            }
          },
          false
        );
      }
    },
    // 商品名称下拉框行数据单击事件
    onRowChange (ref, selectedRow) {
      if (!selectedRow) return;

      this.currentValue = selectedRow[this.labelField];
      Object.keys(selectedRow).forEach(key => {
        this.$set(this.formData, key, selectedRow[key]);
      });
    },
    // 显示下拉框时
    onShow (e) {
      this.treeSuffixIcon = "el-icon-yrt-xiangxiajiantou1 dropdown";
      this.$refs.dropdownTable.setCurrentRow(this.currentRow);

      this.$nextTick(() => {
        const index = this.dataList.findIndex(item => item === this.currentRow);
        const refId = "row" + index;
        const el = this.$refs[refId];
        if (el) el.scrollIntoView({ block: "center" }); // 滚动到可视区域
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.table-select {
  display: inline-block;
  width: 100%;
}

.input {
  ::v-deep .el-input__icon.el-icon-yrt-xiangxiajiantou1 {
    transition: all 0.6s;
    -moz-transition: all 0.6s; /* Firefox 4 */
    -webkit-transition: all 0.6s; /* Safari and Chrome */
    -o-transition: all 0.6s; /* Opera */
    height: 36px;
    padding-top: 4px;
    &.dropdown {
      -webkit-transform: rotateZ(-180deg) translateY(-4px); /* Safari 和 Chrome */
    }
  }
  &.el-input--mini {
    ::v-deep .el-input__icon.el-icon-yrt-xiangxiajiantou1 {
      height: 33px;
    }
  }
  ::v-deep .el-input__suffix {
    right: 1px;
  }
}
.input-popover {
  .el-popover__title {
    margin-bottom: 0px;
  }
  .dropdown-table {
    ::v-deep .cell {
      cursor: pointer;
    }
  }
}
</style>
